using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Input;

namespace One_Crappy_RPG
{
    public class BattleScreen : GameScreen
    {
        ContentManager content;
        GameScreen ParentMap;

        Texture2D Background;
        Texture2D AnimatedBG;
        Vector2 AnimatedBGPosition1 = Vector2.Zero;
        Vector2 AnimatedBGPosition2 = Vector2.Zero;

        Texture2D BattleHUD;
        Rectangle BattleHUDRect;
        Texture2D BattleHUDSubMenu;
        MenuScrollBar SubScrollBar;

        Texture2D Cursor;
        Vector2 CursorPosition = Vector2.Zero;

        Menu CombatMenu = new Menu(new Vector2(250.0f, 442.0f));
        Menu MonsterList = new Menu(new Vector2(25.0f, 422.0f));
        Menu PlayerList = new Menu(new Vector2(400.0f, 422.0f));
        Menu SubMenu = new Menu(new Vector2(25.0f, 422.0f));
        string[] SubMenuKeys;

        List<Hero> PlayerParty;
        List<Monster> Enemies;
        List<Creature> TurnOrder = new List<Creature>();
        Creature ActiveMob;
        List<Monster> Casualties = new List<Monster>();

        Creature PlayerTarget;
        Spell SelectedSpell;
        int TurnIndex = 0;

        bool IsInSubMenu = false;
        bool AnimationPlaying = false;

        public BattleScreen(List<Hero> party, List<Monster> monsters, GameScreen callingMap, Texture2D bg, Texture2D animbg)
        {
            isActive = true;
            hasFocus = true;

            PlayerParty = party;
            Enemies = monsters;
            Background = bg;
            AnimatedBG = animbg;
            ParentMap = callingMap;
            TurnOrder.Clear();
        }

        public override void Initialize()
        {
            base.Initialize();

            AnimatedBGPosition2.X = 800.0f;

            MenuItem Item;

            Item = new MenuItem("Fight");
            Item.Activate += Menu_Fight;
            CombatMenu.AddItem(Item);

            Item = new MenuItem("Magic");
            Item.Activate += Menu_Magic;
            CombatMenu.AddItem(Item);

            Item = new MenuItem("Item");
            Item.Activate += Menu_Item;
            CombatMenu.AddItem(Item);

            Item = new MenuItem("Run");
            Item.Activate += Menu_Run;
            CombatMenu.AddItem(Item);

            //Empty strings to serve as nothing selected
            Item = new MenuItem(string.Empty);
            Item.Visible = false;
            PlayerList.Items.Add(Item);

            Item = new MenuItem(string.Empty);
            Item.Visible = false;
            MonsterList.Items.Add(Item);

            //Add the 16 SubMenu Items
            for (int row = 0; row < 4; row++)
            {
                for (int col = 0; col < 4; col++)
                {
                    Item = new MenuItem(string.Empty);
                    //TODO: Figure out positions
                    Item.Position.Y = SubMenu.Position.Y + 5 + (row * 30);
                    Item.Position.X = SubMenu.Position.X + 5 + (col * 175);

                    SubMenu.Items.Add(Item);
                }
            }
        }

        public override void LoadContent()
        {
            if (content == null)
            {
                content = ScreenManager.content;
            }

            base.LoadContent();


            BattleHUD = content.Load<Texture2D>("Art/Combat/BattleUI");
            BattleHUDSubMenu = content.Load<Texture2D>("Art/Combat/BattleUISubMenu");
            Cursor = content.Load<Texture2D>("Art/Combat/Cursor");

            Vector2 battlePosition = new Vector2(0.0f, 400.0f);

            for (int i = 0; i < Enemies.Count; i++ )
            {
                if (Enemies[i].Texture == null)
                {
                    try
                    {
                        Enemies[i].Texture = content.Load<Texture2D>("Art/Monsters/" + Enemies[i].Name);
                    }
                    catch
                    {
                        Enemies[i].Texture = content.Load<Texture2D>("Art/Tiles/Water");
                    }
                }

                MenuItem Item = new MenuItem(Enemies[i].Name);
                MonsterList.AddItem(Item);
                TurnOrder.Add(Enemies[i]);

                //Adjust their positions
                //Y is constant so they all finish drawing on the same line
                battlePosition.Y = 400.0f - Enemies[i].Texture.Height;

                Enemies[i].Position = battlePosition;
                battlePosition.X = battlePosition.X + Enemies[i].Texture.Width;

                //Subscribe to events
                Enemies[i].EventOnDeath += OnMonsterDeath;

            }

            battlePosition.X = ScreenManager.GraphicsDevice.Viewport.Width;

            foreach (Hero heroes in PlayerParty)
            {
                MenuItem Item = new MenuItem(heroes.Name);
                PlayerList.AddItem(Item);
                heroes.InBattle = true;
                TurnOrder.Add(heroes);
                heroes.Position.Y = 400.0f - heroes.Texture.Height;
                heroes.Position.X = battlePosition.X - heroes.Texture.Width;
            }

            DetermineTurnOrder();

            BattleHUDRect = new Rectangle(0,
                            ScreenManager.GraphicsDevice.Viewport.Height - BattleHUD.Height,
                            BattleHUD.Width, 
                            BattleHUD.Height);
        }

        public override void UnloadContent()
        {
            base.UnloadContent();
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            AnimateBackground();

            if (Enemies.Count == 0)  //We have no enemies left, player wins
            {
                EndBattle();
                return;
            }

            //Loop through combatants
            for (int i = 0; i < TurnOrder.Count; i++ )
            {
                TurnOrder[i].Update(gameTime);

                if (TurnOrder[i].MyTurn)
                    ActiveMob = TurnOrder[i];
            }

            //Skip rest of the code if a turn is animating
            if (ActiveMob.TurnInProgress)
                return;

            //Update party text
            for (int i = 0; i < PlayerList.Items.Count; i++)
            {
                if (PlayerList.Items[i].Visible)
                {

                    string status = PlayerParty[i - 1].Name + "     HP: " +
                        PlayerParty[i - 1].Stats.CurrentHealth.ToString() +
                        " / " +
                        PlayerParty[i - 1].Stats.MaxHealth.ToString() +
                        "   MP: " +
                        PlayerParty[i - 1].Stats.CurrentMP.ToString() +
                        " / " +
                        PlayerParty[i - 1].Stats.MaxMP.ToString();

                    PlayerList.Items[i].Name = status;
                }
            }

            if (!ActiveMob.MyTurn || ActiveMob.Stats.CurrentHealth == 0)
            {
                //Increment/Loop the turn index and notify the next guy
                //it's his turn
                TurnIndex = (TurnIndex + TurnOrder.Count - 1) % TurnOrder.Count;
                TurnOrder[TurnIndex].MyTurn = true;
                ActiveMob = TurnOrder[TurnIndex];
            }
            else if (ActiveMob is Monster)
            {
                ActiveMob.HandleTurn(TurnOrder);
            }

            if (ActiveMob is Hero && ActiveMob.SpellBook.Keys.Count == 0)
            {
                //Disable the spell menu item if they don't know any spells
                CombatMenu.Items[1].Enabled = false;
            }

            HandleInput();
            CalculateCursorPosition();  
        }

        private void EndBattle()
        {
            this.isActive = false;
            this.hasFocus = false;

            ParentMap.isActive = true;
            ParentMap.hasFocus = true;

            ScreenManager.RemoveScreen(this);
        }

        private void CalculateCursorPosition()
        {
            if (PlayerTarget == null && !IsInSubMenu)
            {
                CursorPosition = CombatMenu.SelectedItem.Position;
                CursorPosition.X -= Cursor.Width;
            }
            else if (PlayerTarget != null)
            {
                CursorPosition = PlayerTarget.Position;
                CursorPosition.X -= Cursor.Width - 10;
            }
            else if (IsInSubMenu)
            {
                CursorPosition = SubMenu.SelectedItem.Position;
                CursorPosition.X -= Cursor.Width - 2;
            }
        }

        private void AnimateBackground()
        {
            if (AnimatedBG == null)
                return;

            if (AnimatedBGPosition1.X + AnimatedBG.Width < 0)
            {
                AnimatedBGPosition1.X += 2 * AnimatedBG.Width - 1;
            }
            else
            {
                AnimatedBGPosition1.X -= 0.2f;
            }

            if (AnimatedBGPosition2.X + AnimatedBG.Width < 0)
            {
                AnimatedBGPosition2.X += 2 * AnimatedBG.Width - 1;
            }
            else
            {
                AnimatedBGPosition2.X -= 0.2f;
            }
        }

        public override void Draw(GameTime gameTime)
        {
            ScreenManager.spriteBatch.Begin();

            if (AnimatedBG != null)
            {
                ScreenManager.spriteBatch.Draw(AnimatedBG,
                                               AnimatedBGPosition1,
                                               Color.White);

                ScreenManager.spriteBatch.Draw(AnimatedBG,
                                               AnimatedBGPosition2,
                                               Color.White);
            }

            ScreenManager.spriteBatch.Draw(Background,
                                           new Vector2(0.0f, 0.0f),
                                           Color.White);

            foreach (Creature mob in TurnOrder)
            {               
                mob.Draw(ScreenManager.spriteBatch);
            }

            DrawBattleUI();

            ScreenManager.spriteBatch.End();

            base.Draw(gameTime);
        }

        private void DrawBattleUI()
        {
            if (!IsInSubMenu)
            {
                ScreenManager.spriteBatch.Draw(BattleHUD,
                                               BattleHUDRect,
                                               Color.White);

                if (ActiveMob is Hero && !ActiveMob.TurnInProgress)
                {
                    CombatMenu.Draw(ScreenManager.spriteBatch);
                }

                PlayerList.Draw(ScreenManager.spriteBatch);
                MonsterList.Draw(ScreenManager.spriteBatch);
            }
            else
            {
                ScreenManager.spriteBatch.Draw(BattleHUDSubMenu,
                               BattleHUDRect,
                               Color.White);

                SubMenu.Draw(ScreenManager.spriteBatch);
            }

            if (ActiveMob is Hero)
            {
                ScreenManager.spriteBatch.Draw(Cursor, CursorPosition, Color.White);
            }
        }

        public override void HandleInput()
        {
            InputManager.Update();

            if (PlayerTarget != null)
            #region Handle Targetting
            {

                //Back out
                if (InputManager.WasNewKeyPress(Keys.Escape))
                {
                    PlayerTarget = null;
                }
                //Activate the command
                else if (InputManager.WasNewKeyPress(Keys.Enter))
                {
                    CombatMenu.SelectedItem.PerformActivate();
                    PlayerTarget = null;
                }
                //Change target
                else if (InputManager.WasNewKeyPress(Keys.Down) ||
                         InputManager.WasNewKeyPress(Keys.Left))
                {
                    FindPreviousTarget();
                }
                //Change target
                else if (InputManager.WasNewKeyPress(Keys.Up) ||
                    InputManager.WasNewKeyPress(Keys.Right))
                {
                    FindNextTarget();
                }
            }
            #endregion
            else if (PlayerTarget == null && !IsInSubMenu)
            #region Handle Base Menu Options
            {
                if (InputManager.WasNewKeyPress(Keys.Enter))
                {
                    if (CombatMenu.SelectedItem.Name == "Fight")
                    {
                        PlayerTarget = Enemies[0];
                    }
                    else if (CombatMenu.SelectedItem.Name == "Magic")
                    {
                        //Activate spell menu
                        IsInSubMenu = true;

                        SubMenuKeys = new string[ActiveMob.SpellBook.Keys.Count];
                        ActiveMob.SpellBook.Keys.CopyTo(SubMenuKeys, 0);

                        SubScrollBar = new MenuScrollBar((int)Math.Ceiling(SubMenuKeys.Length / 16.0f));

                        SubMenu.SelectedIndex = 0;                        
                    }
                    else if (CombatMenu.SelectedItem.Name == "Item")
                    {
                        //Activate item menu
                    }
                    else if (CombatMenu.SelectedItem.Name == "Run")
                    {
                        //Run away!
                    }
                }
                else if (InputManager.WasNewKeyPress(Keys.Down))
                {
                    CombatMenu.SelectNext();
                }
                else if (InputManager.WasNewKeyPress(Keys.Up))
                {
                    CombatMenu.SelectPrevious();
                }
            }
            #endregion
            else if (IsInSubMenu)
            {
                //Back out
                if (InputManager.WasNewKeyPress(Keys.Escape))
                {
                    PlayerTarget = null;
                    IsInSubMenu = false;
                }

                #region Spell Menu Code
                else if (CombatMenu.SelectedItem.Name == "Magic")
                {
                    PopulateSpellMenu();

                    int newItem = SubMenu.SelectedIndex;

                    if (InputManager.WasNewKeyPress(Keys.Enter))
                    {
                        if (SubMenu.SelectedItem.Name != string.Empty && SubMenu.SelectedItem.Enabled)
                        {
                            SelectedSpell = ActiveMob.SpellBook[SubMenu.SelectedItem.Name];

                            if (SelectedSpell.Hostile)
                            {
                                PlayerTarget = Enemies[0];
                            }
                            else
                            {
                                PlayerTarget = ActiveMob;
                            }
                        }
                    }
                    else if (InputManager.WasNewKeyPress(Keys.Up))
                    {
                        newItem -= 4;

                        if (newItem < 0)
                        {
                            SubScrollBar.Scroll(-1);
                            newItem += 4;
                        }
                    }
                    else if (InputManager.WasNewKeyPress(Keys.Down))
                    {
                        newItem += 4;

                        if (newItem > 15)
                        {
                            SubScrollBar.Scroll(1);
                            newItem -= 4;
                        }
                    }
                    else if (InputManager.WasNewKeyPress(Keys.Left))
                    {
                        newItem--;

                        if (newItem < 0)
                        {
                            SubScrollBar.Scroll(-1);
                            newItem++;
                        }
                    }
                    else if (InputManager.WasNewKeyPress(Keys.Right))
                    {
                        newItem++;

                        if (newItem > 15)
                        {
                            SubScrollBar.Scroll(1);
                            newItem--;
                        }
                    }

                    SubMenu.SelectedIndex = newItem;
                }
                #endregion
                #region Item Menu Code
                else if (CombatMenu.SelectedItem.Name == "Item")
                {
                }
                #endregion
            }
        }

        private void PopulateSpellMenu()
        { 
            for (int row = 0; row < 4; row++)
            {
                for (int col = 0; col < 4; col++)
                {
                    int index = ((row * 4) + col);

                    //Make sure the spell we're trying to get is within bounds
                    if (SubMenuKeys.GetLength(0) > index + (index * SubScrollBar.Value))
                    {
                        SubMenu.Items[index].Name = SubMenuKeys[index * SubScrollBar.Value];

                        //Disable spells we don't have the MP for
                        if (ActiveMob.Stats.CurrentMP < ActiveMob.SpellBook[SubMenu.Items[index].Name].MP)
                            SubMenu.Items[index].Enabled = false;
                        else
                            SubMenu.Items[index].Enabled = true;
                    }
                    else
                    {
                        SubMenu.Items[index].Name = string.Empty;
                    }
                }
            }
        }

        private void FindNextTarget()
        {
            int index;

            if (PlayerTarget is Hero)
            {
                index = PlayerParty.IndexOf((Hero)PlayerTarget);

                if (index + 1 >= PlayerParty.Count)
                {
                    PlayerTarget = Enemies[0];
                    return;
                }

                PlayerTarget = PlayerParty[index + 1];
            }
            else if (PlayerTarget is Monster)
            {
                index = Enemies.IndexOf((Monster)PlayerTarget);

                if (index + 1 >= Enemies.Count)
                {
                    PlayerTarget = PlayerParty[0];
                    return;
                }

                PlayerTarget = Enemies[index + 1];
            }

        }

        private void FindPreviousTarget()
        {
            int index;

            if (PlayerTarget is Hero)
            {
                index = PlayerParty.IndexOf((Hero)PlayerTarget);

                if (index - 1 < 0)
                {
                    PlayerTarget = Enemies[Enemies.Count - 1];
                    return;
                }

                PlayerTarget = PlayerParty[index - 1];
            }
            else if (PlayerTarget is Monster)
            {
                index = Enemies.IndexOf((Monster)PlayerTarget);

                if (index - 1 < 0)
                {
                    PlayerTarget = PlayerParty[PlayerParty.Count - 1];
                    return;
                }

                PlayerTarget = Enemies[index - 1];
            }
               
        }

        void Menu_Fight(object sender, EventArgs args)
        {
            ActiveMob.Attack(PlayerTarget);
        }

        void Menu_Magic(object sender, EventArgs args)
        {
            ActiveMob.CastSpell(SelectedSpell, PlayerTarget);
            IsInSubMenu = false;
        }

        void Menu_Item(object sender, EventArgs args)
        {
        }

        void Menu_Run(object sender, EventArgs args)
        {
            //Temporary: 50% chance to flee
            if (PlayerParty[0].rng.NextDouble() <= 0.5)
            {
                EndBattle();
            }
        }

        void DetermineTurnOrder()
        {
            TurnOrder.Sort(delegate(Creature a, Creature b) { return b.Stats.Speed.CompareTo(a.Stats.Speed); });
            TurnOrder[0].MyTurn = true;
            ActiveMob = TurnOrder[0];
        }

        void OnMonsterDeath(Creature deceased)
        {
            //Add to Casualties list for possible rez & rewarding XP
            Casualties.Add((Monster)deceased);

            //Remove them from the fight itself
            Enemies.Remove((Monster)deceased);
            TurnOrder.Remove(deceased);

            //Play some kind of death animation
        }
    }
}
